package com.zz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zz.common.R;
import com.zz.dto.ActivityDto;
import com.zz.entity.*;
import com.zz.mapper.*;
import com.zz.service.ActivityService;
import com.zz.utils.AesEncryptUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 社团活动
 * @author HUAWEI
 */
@Service
@Slf4j
@Validated
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements ActivityService {

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private ClubMapper clubMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ApplicationAuditingMapper applicationAuditingMapper;

    @Autowired
    private SystemNoticeMapper systemNoticeMapper;

    @Autowired
    private PublicityMapper publicityMapper;

    @Value("${qiniu.fileDomain}")
    private String fileDomain;

    /**
     * 活动信息分页查询
     * 周紫
     * */
    @Override
    public R<Page> page(int page, int pageSize, @Nullable String name) {
        // 构造分页构造器
        Page<Activity> pageInfo = new Page<>(page, pageSize);
        Page<ActivityDto> activityDtoPage = new Page<>(page, pageSize);

        // 构造条件构造器
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper();
        // 添加过滤条件(isNotEmpty(name))
        queryWrapper.like(name != null,Activity::getName,name);
        //显示已经被审核通过可以举办的活动 operate:是否通过 status：是否审核
        queryWrapper.eq(Activity::getOperate, 1).eq(Activity::getStatus, 1).
                eq(Activity::getApply, 1);

        // 执行分页查询
        // 在page方法内部会将查好的数据封装，赋好值给pageInfo
        activityMapper.selectPage(pageInfo,queryWrapper);

        // 对象拷贝(除了records,records其实就是页面中一整行一整行数据)
        BeanUtils.copyProperties(pageInfo,activityDtoPage,"records");

        List<Activity> records = pageInfo.getRecords();
        // 遍历list集合对象,item即为获取到的一个个Activity对象
        List<ActivityDto> list = records.stream().map((item) -> {
            ActivityDto activityDto = new ActivityDto();
            // 将其Activity中的数据复制给DishDto
            BeanUtils.copyProperties(item,activityDto);

            int clubId = item.getClubId();//分类id
            // 根据id查询分类对象
            Club club = clubMapper.selectById(clubId);

            if (club != null){
                activityDto.setClubName(club.getName());
            }
            //图片路径解密
            String image = activityDto.getImage();
            if (image != null){
                image = AesEncryptUtils.decrypt(image);
                activityDto.setImage(fileDomain+"/"+image);
            }

            return activityDto;
        }).collect(Collectors.toList());// 把以上创建的dto对象都收集起来


        activityDtoPage.setRecords(list);

        return R.success(activityDtoPage);
    }

    /**
     * 负责人申请活动
     * @param activity
     * @return
     */
    @Override
    public R<String> applyActivity(Activity activity) {
        // 获取活动id
        int activityId = activity.getId();

        // 条件过滤器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activityId);

        Activity one = activityMapper.selectOne(wrapper);

        // 设置apply=1（已申请），并且申请时间为当前时间
        one.setApply(1);
        one.setRegisterTime(new Date(System.currentTimeMillis()));

        // 数据库更新字段
        activityMapper.updateById(one);

        return R.success("成功申请活动！");
    }

    @Override
    public R<List<ActivityDto>> showLatestActivity(int start, int end) {
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 获取当前时间
        Date date = new Date(System.currentTimeMillis());

        wrapper.orderByAsc(Activity::getTime)
                .eq(Activity::getApply, 1)
                .eq(Activity::getStatus, 1)
                .eq(Activity::getOperate, 1)
                .ge(Activity::getTime, date);
        // 将所有符合条件的活动按举办时间降序排列
        List<Activity> activities = activityMapper.selectList(wrapper);
        List<ActivityDto> activityDtos = new ArrayList<>();
        int index = 1;

        for (Activity activity : activities) {
            ActivityDto activityDto = new ActivityDto();
            // 拷贝对象
            BeanUtils.copyProperties(activity, activityDto);

            // 获取详细信息
            Club club = clubMapper.selectById(activity.getClubId());

            activityDto.setClubName(club.getName());
            // 设置宣传内容
            LambdaQueryWrapper<Publicity> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(Publicity::getActivityId, activity.getId());
            Publicity publicity = publicityMapper.selectOne(wrapper1);
            if (publicity != null){
                activityDto.setPublicityInfo(publicity.getScheme());
            }
            //图片路径解密
            String image = activityDto.getImage();
            if (image != null){
                image = AesEncryptUtils.decrypt(image);
                activityDto.setImage(fileDomain+"/"+image);
            }

            if (index >=start && index <=end){
                activityDtos.add(activityDto);
            }

            index++;
        }

        return R.success(activityDtos);

    }

    /**
     * @param activity
     * 朱彦燕
     * 用户报名参加活动
     * 测试成功
     */
    @Override
    public R<String> applyActivity(Activity activity, HttpServletRequest request) {
        // 获取当前用户的用户名
        String userName = (String) request.getSession().getAttribute("user");

        // 查找当前用户
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(User::getName, userName);
        User user = userMapper.selectOne(userWrapper);

        // 获取用户学号
        int userId = user.getId();
        int activityId = activity.getId();

        // 判断此活动是否存在
        Activity activity1 = activityMapper.selectById(activityId);
        if (activity1 == null){
            return R.error("此活动不存在!");
        }

        // 判断此用户是否已经报名该活动
        LambdaQueryWrapper<ApplicationAuditing> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApplicationAuditing::getUserId, userId).eq(ApplicationAuditing::getActivityId, activityId)
                .eq(ApplicationAuditing::getStatus, 0).eq(ApplicationAuditing::getOperate, 0);
        ApplicationAuditing applicationAuditing1 = applicationAuditingMapper.selectOne(wrapper);
        if (applicationAuditing1 != null){
            return R.error("此用户已经报名该活动！不能重复报名！");
        }

        // 创建报名审核表的对象
        ApplicationAuditing applicationAuditing = new ApplicationAuditing();
        applicationAuditing.setUserId(userId);
        applicationAuditing.setActivityId(activityId);
        applicationAuditing.setRegisterTime(new Date(System.currentTimeMillis()));

        // 数据库中添加数据
        applicationAuditingMapper.insert(applicationAuditing);

        return R.success("成功报名活动！");

    }

    /**
     * 展示所有社团申请举办活动的信息（admin）
     * @return
     */
    @Override
    public R<List<Activity>> showApplication(@Nullable String activityName) {
        // 未审核
        int status=0;
        // 已申请
        int apply = 1;
        // 条件过滤器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 已申请未审核
        wrapper.eq(Activity::getStatus, status).eq(Activity::getApply, apply);
        wrapper.like(activityName != null, Activity::getName, activityName);

        List<Activity> list = activityMapper.selectList(wrapper);
        return R.success(list);
    }


    /**
     * 同意活动申请（admin）
     * @param activity
     * @return
     */
    @Override
    public R<String> agree(Activity activity) {
        // 根据活动id查找活动
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activity.getId());
        Activity one = activityMapper.selectOne(wrapper);

        // 修改操作字段operate为1,表示通过,status修改为1，表示已经审核过
        one.setOperate(1);
        one.setStatus(1);
        // 同步数据库操作
        activityMapper.updateById(one);

        // 记录系统通知信息
        Club club = clubMapper.selectById(one.getClubId());
        SystemNotice systemNotice = new SystemNotice();
        systemNotice.setUserId(one.getLeaderId());
        systemNotice.setTitle("您收到一条来自学校管理员的活动通知！");
        systemNotice.setInfo(club.getName()+"社团负责人您好！恭喜您申请举办的活动"+one.getName()+"成功通过审核！");
        systemNotice.setTime(new Date(System.currentTimeMillis()));

        systemNoticeMapper.insert(systemNotice);

        return R.success("同意社团活动申请");
    }

    /**
     * 拒绝活动申请
     * @param activity
     * @return
     */
    @Override
    public R<String> decline(Activity activity) {
        // 根据活动id查找活动
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activity.getId());
        Activity one = activityMapper.selectOne(wrapper);

        // 操作字段operate默认为0,表示不通过,不用修改,status修改为1，表示已经审核过
        one.setStatus(1);
        one.setOperate(0);
        activityMapper.updateById(one);

        // 记录系统通知信息
        Club club = clubMapper.selectById(one.getClubId());
        SystemNotice systemNotice = new SystemNotice();
        systemNotice.setUserId(one.getLeaderId());
        systemNotice.setTitle("您收到一条来自学校管理员的活动通知！");
        systemNotice.setInfo(club.getName()+"社团负责人您好！很遗憾！您申请举办的活动"+one.getName()+"没有通过审核！若想举办活动，请再次申请！");
        systemNotice.setTime(new Date(System.currentTimeMillis()));

        systemNoticeMapper.insert(systemNotice);

        return R.success("拒绝社团活动申请");
    }

    /**
     * 社团负责人：往活动草稿箱里增加活动（draft）
     * @param activity
     * @param request
     * @return
     */
    @Override
    public R<String> addActivity(Activity activity, HttpServletRequest request) {
        // 从session中获取本社团id
        int clubId = (int) request.getSession().getAttribute("club");
        if (clubId == 0){
            return R.error("您还未选择社团进行管理！");
        }

        // 获得活动名称
        String name = activity.getName();

        // 查询数据库是否已经存在该活动
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getName, name);
        Activity one = activityMapper.selectOne(wrapper);

        // 如果存在，返回错误提示信息
        if (one != null){
            return R.error("活动名称重复！");
        }

        // 从session中获取当前用户用户名
        String userName = (String) request.getSession().getAttribute("user");
        // 条件查询器
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        // 根据用户名查找用户
        userWrapper.eq(User::getName, userName);
        User user = userMapper.selectOne(userWrapper);
        activity.setLeaderId(user.getId());

        activity.setClubId(clubId);

        // 插入数据库
        activityMapper.insert(activity);
        return R.success( "成功增加活动");
    }

    /**
     * 活动草稿箱：删除活动（draft）
     * @param activity
     * @return
     */
    @Override
    public R<String> deleteActivity(Activity activity) {
        // 获得活动id
        int activityId = activity.getId();

        // 条件查询器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activityId);

        // 判断活动是否存在
        Activity one = activityMapper.selectOne(wrapper);
        if (one == null){
            return R.error("此活动不存在！");
        }

        // 从数据库中删除活动
        activityMapper.delete(wrapper);
        return R.success("成功删除活动！");
    }

    /**
     * 活动草稿箱：编辑活动（draft）
     * @param activity
     * @return
     */
    @Override
    public R<String> editActivity(Activity activity) {
        // 获取社团编码
        int activityId = activity.getId();

        // 条件查询器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activityId);
        Activity one = activityMapper.selectOne(wrapper);
        // 更改数据
        one.setName(activity.getName());
        one.setTime(activity.getTime());
        one.setPlace(activity.getPlace());
        one.setNumber(activity.getNumber());
        one.setIntroduce(activity.getIntroduce());

        // 同步到数据库
        activityMapper.updateById(one);

        return R.success("成功修改活动！");
    }

    /**
     * 社团草稿箱活动分页展示（draft）
     * @param page
     * @param pageSize
     * @param request
     * @return
     */
    @Override
    public R<Page> activityList(int page, int pageSize, @Nullable String activityName, HttpServletRequest request) {
        // 获取当前社团id
        int clubId = (int) request.getSession().getAttribute("club");
        log.info("当前社团id:{}",clubId);
        if (clubId == 0){
            return R.error("您还未选择社团进行管理！");
        }

        // 构造分页构造器
        Page<Activity> pageInfo = new Page<>(page, pageSize);

        // 构造条件构造器,社团id+apply
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 显示本社团未申请的活动
        wrapper.eq(Activity::getClubId, clubId).eq(Activity::getApply, 0L);
        // 活动名称模糊匹配
        wrapper.like(activityName != null, Activity::getName, activityName);

        // 执行分页查询
        //在page方法内部会将查好的数据封装，赋好值给pageInfo
        activityMapper.selectPage(pageInfo, wrapper);

        return R.success(pageInfo);
    }


    /**
     * 撤销举办活动的申请（leader）
     * @param activity
     * @return
     */
    @Override
    public R<String> cancelActivity(Activity activity) {
        // 获取活动id
        int activityId = activity.getId();

        // 条件过滤器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId, activityId);

        Activity one = activityMapper.selectOne(wrapper);

        // 如果申请的活动已经被审核，则无法撤销申请
        if (one.getStatus() == 1){
            return R.error("该活动已经被审核，无法撤销申请！");
        }
        // 设置apply=0（撤销申请），并且申请时间为当前时间
        one.setApply(0);
        one.setRegisterTime(null);

        // 数据库更新字段
        activityMapper.updateById(one);

        return R.success("成功撤销活动申请！");
    }


    /**
     * 社团负责人：展示已经被审核通过的活动（leader）
     * @param page
     * @param pageSize
     * @param request
     * @return
     */
    @Override
    public R<Page> approvedActivity(int page, int pageSize, HttpServletRequest request) {
        // 分页构造器
        Page<Activity> pageInfo = new Page<>(page, pageSize);
        Page<ActivityDto> activityDtoPage = new Page<>(page, pageSize);

        // 获取社团id
        int clubId = (int) request.getSession().getAttribute("club");
        if (clubId == 0){
            return R.error("您还未选择社团进行管理！");
        }

        // 条件查询器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 属于本社团的活动：已申请 apply=1 已审核 status=1 已通过 operate=1
        wrapper.eq(Activity::getApply, 1).eq(Activity::getStatus, 1).
                eq(Activity::getOperate, 1).eq(Activity::getClubId, clubId);

        // 执行分页查询
        // 在page方法内部会将查好的数据封装，赋好值给pageInfo
        activityMapper.selectPage(pageInfo,wrapper);

        // 对象拷贝(除了records,records其实就是页面中一整行一整行数据)
        BeanUtils.copyProperties(pageInfo,activityDtoPage,"records");

        List<Activity> records = pageInfo.getRecords();
        // 遍历list集合对象,item即为获取到的一个个Activity对象
        List<ActivityDto> list = records.stream().map((item) -> {
            ActivityDto activityDto = new ActivityDto();
            // 将其Activity中的数据复制给DishDto
            BeanUtils.copyProperties(item,activityDto);

            // 根据id查询分类对象
            Club club = clubMapper.selectById(clubId);

            if (club != null){
                activityDto.setClubName(club.getName());
            }
            return activityDto;
        }).collect(Collectors.toList());// 把以上创建的dto对象都收集起来

        activityDtoPage.setRecords(list);

        return R.success(activityDtoPage);
    }

    /**
     * 社团负责人：展示已经被审核驳回的活动（leader）
     * @param page
     * @param pageSize
     * @param request
     * @return
     */
    @Override
    public R<Page> notApprovedActivity(int page, int pageSize, HttpServletRequest request) {
        // 分页构造器
        Page<Activity> pageInfo = new Page<>(page, pageSize);
        Page<ActivityDto> activityDtoPage = new Page<>(page, pageSize);

        // 获取社团id
        int clubId = (int) request.getSession().getAttribute("club");
        if (clubId == 0){
            return R.error("您还未选择社团进行管理！");
        }

        // 条件查询器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 属于本社团的活动：已申请 apply=1 已审核 status=1 未通过 operate=0
        wrapper.eq(Activity::getApply, 1).eq(Activity::getStatus, 1).
                eq(Activity::getOperate, 0).eq(Activity::getClubId, clubId);

        // 执行分页查询
        // 在page方法内部会将查好的数据封装，赋好值给pageInfo
        activityMapper.selectPage(pageInfo,wrapper);

        // 对象拷贝(除了records,records其实就是页面中一整行一整行数据)
        BeanUtils.copyProperties(pageInfo,activityDtoPage,"records");

        List<Activity> records = pageInfo.getRecords();
        // 遍历list集合对象,item即为获取到的一个个Activity对象
        List<ActivityDto> list = records.stream().map((item) -> {
            ActivityDto activityDto = new ActivityDto();
            // 将其Activity中的数据复制给DishDto
            BeanUtils.copyProperties(item,activityDto);

            // 根据id查询分类对象
            Club club = clubMapper.selectById(clubId);

            if (club != null){
                activityDto.setClubName(club.getName());
            }
            return activityDto;
        }).collect(Collectors.toList());// 把以上创建的dto对象都收集起来

        activityDtoPage.setRecords(list);

        return R.success(activityDtoPage);
    }

    @Override
    public R<Page> reviewedActivity(int page, int pageSize, HttpServletRequest request) {
        // 分页构造器
        Page<Activity> pageInfo = new Page<>(page, pageSize);
        Page<ActivityDto> activityDtoPage = new Page<>(page, pageSize);

        // 获取社团id
        int clubId = (int) request.getSession().getAttribute("club");
        if (clubId == 0){
            return R.error("您还未选择社团进行管理！");
        }

        // 条件查询器
        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        // 属于本社团的活动：已申请 apply=1 待审核 status=0
        wrapper.eq(Activity::getApply, 1).eq(Activity::getStatus, 0)
                .eq(Activity::getClubId, clubId);

        // 执行分页查询
        // 在page方法内部会将查好的数据封装，赋好值给pageInfo
        activityMapper.selectPage(pageInfo,wrapper);

        // 对象拷贝(除了records,records其实就是页面中一整行一整行数据)
        BeanUtils.copyProperties(pageInfo,activityDtoPage,"records");

        List<Activity> records = pageInfo.getRecords();
        // 遍历list集合对象,item即为获取到的一个个Activity对象
        List<ActivityDto> list = records.stream().map((item) -> {
            ActivityDto activityDto = new ActivityDto();
            // 将其Activity中的数据复制给DishDto
            BeanUtils.copyProperties(item,activityDto);

            // 根据id查询分类对象
            Club club = clubMapper.selectById(clubId);

            if (club != null){
                activityDto.setClubName(club.getName());
            }
            return activityDto;
        }).collect(Collectors.toList());// 把以上创建的dto对象都收集起来

        activityDtoPage.setRecords(list);

        return R.success(activityDtoPage);
    }

    @Override
    public R<ActivityDto> activityInfo(int activityId) {
        // 查询活动
        Activity activity = activityMapper.selectById(activityId);

        // 新建返回对象
        ActivityDto activityDto = new ActivityDto();
        BeanUtils.copyProperties(activity,activityDto);

        Club club = clubMapper.selectById(activity.getClubId());
        if (club != null){
            activityDto.setClubName(club.getName());
            activityDto.setClassify(club.getClassify());
        }

        // publicity条件查询器
        LambdaQueryWrapper<Publicity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Publicity::getActivityId, activityId);
        Publicity publicity = publicityMapper.selectOne(wrapper);
        if (publicity != null){
            activityDto.setPublicityInfo(publicity.getScheme());
            activityDto.setExpected(publicity.getExpected());
        }

        return R.success(activityDto);
    }

    @Override
    public R<List<ActivityDto>> showByClassify(@Nullable String classify) {
        // 查询社团
        LambdaQueryWrapper<Club> clubWrapper = new LambdaQueryWrapper<>();
        clubWrapper.like(classify != null, Club::getClassify, classify);
        List<Club> clubs = clubMapper.selectList(clubWrapper);
        Set<Integer> clubIds = new HashSet<>();
        for (Club club : clubs) {
            clubIds.add(club.getId());
        }

        // 查询活动
        LambdaQueryWrapper<Activity> activityWrapper = new LambdaQueryWrapper<>();
        activityWrapper.in(Activity::getClubId, clubIds);
        List<Activity> activities = activityMapper.selectList(activityWrapper);
        ArrayList<ActivityDto> activityDtos = new ArrayList<>();
        for (Activity activity : activities) {
            // 新建返回对象
            ActivityDto activityDto = new ActivityDto();
            BeanUtils.copyProperties(activity,activityDto);

            Club club = clubMapper.selectById(activity.getClubId());
            if (club != null){
                activityDto.setClubName(club.getName());
                activityDto.setClassify(club.getClassify());
            }

            // publicity条件查询器
            LambdaQueryWrapper<Publicity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Publicity::getActivityId, activity.getId());
            Publicity publicity = publicityMapper.selectOne(wrapper);
            if (publicity != null){
                activityDto.setPublicityInfo(publicity.getScheme());
                activityDto.setExpected(publicity.getExpected());
            }
            //图片路径解密
            String image = activityDto.getImage();
            if (image != null){
                image = AesEncryptUtils.decrypt(image);
                activityDto.setImage(fileDomain+"/"+image);
            }

            activityDtos.add(activityDto);
        }

        return R.success(activityDtos);
    }


}
